Skip to content

07 提示词工程面试题

1、System Prompt有什么作用?

System Prompt 是给模型的最高层指令,用来定义模型在这次任务里的角色、目标、边界和输出要求。

普通用户输入是“这次要做什么”,System Prompt 更像是“你应该以什么身份、按什么规则去做”。

它通常会包含几类内容:

  • 角色定位:你是客服助手、代码助手、数据分析助手,还是销售顾问
  • 任务目标:主要解决什么问题
  • 行为规则:能做什么,不能做什么
  • 输出格式:用中文还是英文,输出 JSON 还是 Markdown
  • 工具规则:什么时候调用工具,什么时候不要调用工具
  • 安全边界:遇到敏感、危险、越权请求时怎么处理

例如:

text
你是一个企业知识库问答助手。
回答时只能基于提供的资料,不要编造。
如果资料中没有答案,就回答“暂时没有找到相关信息”。
回答要简洁,优先使用中文。

这个 System Prompt 会明显影响模型行为。没有它,模型可能会凭常识回答;有了它,模型就会更倾向于基于资料回答。

在 Agent 系统里,System Prompt 很重要,因为 Agent 不只是聊天,还可能调用工具、读写数据、执行任务。如果没有清晰的规则,Agent 容易做出超出预期的操作。

2、如何设计Agent的System Prompt?

设计 Agent 的 System Prompt,重点不是写得长,而是把关键规则说清楚。

一个实用的结构通常包括六部分。

第一,说明角色。

text
你是一个面向研发团队的代码分析助手。

第二,说明目标。

text
你的目标是帮助用户理解代码、定位问题、给出可执行的修改建议。

第三,说明输入来源。

text
你可以使用用户问题、当前上下文、工具返回结果来完成任务。

第四,说明工具使用规则。

text
需要实时数据、代码内容或外部信息时,先调用工具。
不要在没有依据时编造文件内容或接口返回。

第五,说明行为边界。

text
不要执行删除、发送、支付等高风险操作,除非用户明确确认。

第六,说明输出要求。

text
回答要简洁,先给结论,再说明原因。涉及代码时给出文件路径和关键位置。

可以写成这样:

text
你是一个代码分析 Agent。
你的任务是帮助用户阅读代码、定位问题、修改实现。
在回答前,先基于工具读取真实代码,不要猜测。
如果需要修改代码,只修改和任务直接相关的部分。
不要做用户没有要求的重构。
回答用中文,语言简洁。

在 LangChain v1.0 中,如果使用 create_agent,可以通过 system_prompt 传入系统提示词:

python
from langchain.agents import create_agent

agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[search_tool],
    system_prompt="你是一个企业知识库问答助手。回答只能基于检索到的资料。",
)

在 LangGraph v1.0 中,System Prompt 通常会作为消息的一部分进入状态,也可以在节点里统一组装。复杂 Agent 更推荐把提示词组装逻辑放到固定节点中,避免散落在业务代码里。

3、如何限制Agent行为边界?

限制 Agent 行为边界,不能只靠一句“不要乱做”。需要从 Prompt、工具权限、执行层三方面一起控制。

第一,在 System Prompt 里明确规则。

例如:

text
你只能回答和企业内部知识库相关的问题。
如果用户要求你执行删除数据、发送邮件、修改权限等操作,必须先请求人工确认。
不要输出未经验证的结论。

第二,在工具层限制能力。

Agent 能做什么,取决于你给了它什么工具。如果不希望它删除文件,就不要给删除工具。如果必须给,也要加权限校验和人工确认。

第三,在执行层做拦截。

模型可能会生成不合规的工具调用,所以真正执行前还要检查:

python
def before_tool_call(tool_name, args, user):
    if tool_name in ["delete_user", "send_email", "transfer_money"]:
        return require_human_approval(tool_name, args, user)
    return True

第四,对输出做约束。

比如医疗、法律、金融类场景,不能让模型给出确定性承诺,而是要求说明限制和建议咨询专业人员。

第五,记录日志和审计。

只靠当场拦截还不够,生产环境需要记录 Agent 做了什么、为什么做、调用了哪些工具、用户是否确认。

所以边界控制不是 Prompt 一个点的问题,而是:

text
Prompt 说明规则
Tool 限制能力
Runtime 做校验
Human-in-the-loop 管高风险动作
日志负责追踪和复盘

在 LangGraph v1.0 里,这类边界通常可以做成独立节点,比如 review_tool_callhuman_approvalpolicy_check,让 Agent 在执行工具前先走检查流程。

4、如何控制输出格式?

控制输出格式,最直接的方法是在 Prompt 中明确说明格式,并给出模板。

比如要求输出 Markdown:

text
请按以下格式回答:

## 结论
...

## 原因
...

## 建议
...

如果要求输出列表,也要写清楚:

text
请只输出 3 条建议,每条不超过 30 个字。
格式如下:
1. ...
2. ...
3. ...

如果是结构化数据,最好直接给字段定义:

text
请输出 JSON,字段如下:
- title:标题
- summary:摘要
- tags:字符串数组

控制格式时有几个经验。

第一,少用模糊词。

比如“整齐一点”“专业一点”不如直接说“使用 Markdown 表格”。

第二,给模板比只描述更有效。

模型看到完整模板,更容易按模板输出。

第三,限制不要太多。

如果同时要求 JSON、Markdown、表格、自然语言解释,模型容易混乱。

第四,程序侧要校验。

Prompt 能提高概率,但不能保证 100% 正确。真正上线时,仍然要在代码里解析和校验输出。

在 LangChain v1.0 中,如果要稳定拿到结构化结果,更推荐使用 ProviderStrategyToolStrategy 这类结构化输出能力,而不是只靠 Prompt 约束。

5、如何保证输出JSON格式?

严格来说,不能只靠 Prompt 保证 JSON 一定合法。Prompt 只能提高模型按 JSON 输出的概率,真正可靠的做法是“模型约束 + 程序校验 + 失败重试”。

第一步,Prompt 里说清楚只输出 JSON。

text
请只输出合法 JSON,不要输出 Markdown,不要输出解释文字。
字段包括:name、age、tags。

第二步,给出 JSON 示例。

json
{
  "name": "张三",
  "age": 18,
  "tags": ["学生", "篮球"]
}

第三步,使用结构化输出能力。

在 LangChain v1.0 中,可以定义 Pydantic 模型,然后让 Agent 按结构返回:

python
from pydantic import BaseModel, Field
from langchain.agents import create_agent

class UserInfo(BaseModel):
    name: str = Field(description="用户姓名")
    age: int = Field(description="用户年龄")
    tags: list[str] = Field(description="用户标签")

agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[],
    response_format=UserInfo,
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "张三今年18岁,喜欢篮球"}]
})

user_info = result["structured_response"]

LangChain 会根据模型能力选择合适的结构化输出方式。支持原生结构化输出的模型,会走 ProviderStrategy;不支持时,可以通过 ToolStrategy 让模型用工具调用形式返回结构化结果。

第四步,程序侧解析和校验。

即使使用结构化输出,也建议在业务边界做校验。比如年龄不能是负数,字段不能缺失,枚举值必须合法。

第五步,失败时重试或降级。

如果 JSON 解析失败,可以把错误返回给模型,让它重新生成合法 JSON。不要把非法 JSON 直接交给下游系统。

6、什么是Few-shot Prompt?

Few-shot Prompt 指的是在提示词里给模型几个示例,让模型模仿示例的格式、风格或推理方式完成新任务。

它适合用在规则不容易说清楚,但示例一看就懂的场景。

比如做文本分类:

text
请判断用户意图,只输出 intent。

示例1:
用户:我想查一下订单物流
输出:query_logistics

示例2:
用户:我要退货
输出:refund_order

示例3:
用户:怎么修改收货地址
输出:change_address

现在判断:
用户:我的快递到哪了
输出:

模型看到前面的例子,就更容易输出 query_logistics

Few-shot 的价值主要有三个。

第一,统一输出格式。

示例比文字描述更直观。

第二,减少歧义。

有些分类边界很难靠规则写清楚,示例能帮助模型理解。

第三,稳定风格。

比如客服话术、面试题回答、代码注释风格,都可以用示例约束。

但 Few-shot 也有成本。示例会占用 Token,如果示例太多,Prompt 会变长,速度和成本都会受影响。一般只放最有代表性的几个例子,不要把所有历史样本都塞进去。

7、什么是Chain of Thought?

Chain of Thought,通常叫思维链,指的是让模型在回答复杂问题时先进行分步骤思考,再给出答案。

它的作用是提升复杂推理任务的准确率,比如数学题、逻辑推理、多步骤规划、复杂代码分析等。

简单例子:

text
请一步一步分析这个问题,然后给出结论。

相比直接让模型回答,分步骤分析通常更稳,因为模型不会太快跳到结论。

但在实际产品里,不一定要把完整推理过程展示给用户。很多时候更好的做法是:让模型内部分析,最终只输出简洁结论和必要理由。

例如可以要求:

text
请先分析问题,但最终只输出结论、关键原因和建议,不要输出详细思考过程。

这样既能让模型做更充分的判断,又不会把冗长的推理过程暴露给用户。

在 Agent 场景里,Chain of Thought 更常表现为“分步骤执行”:

text
理解任务 → 读取资料 → 调用工具 → 检查结果 → 生成答案

在 LangGraph v1.0 里,这种流程通常不只靠 Prompt,而是通过图结构显式编排,把不同步骤拆成不同节点。这样比让模型在一段 Prompt 里自由发挥更可控。

8、什么是Self-Consistency?

Self-Consistency 是一种提高答案稳定性的方法。

它的思路是:同一个问题让模型生成多次答案,或者走多条推理路径,然后从多个结果中选择最一致、最可靠的那个。

比如一道推理题,模型一次回答可能会出错。如果让它用不同方式推理 5 次,其中 4 次得到同一个结果,那么这个结果通常更可信。

流程大概是:

text
同一个问题

生成多个候选答案

比较候选答案

选择多数一致或评分最高的答案

它适合用在准确率比速度更重要的场景,比如复杂推理、代码方案评审、分类判断、风险识别等。

缺点也明显:成本更高,速度更慢。因为它需要多次调用模型,或者一次生成多个候选结果。

在工程里不一定每个问题都用 Self-Consistency。一般只在高价值、易出错、需要更稳的任务上使用。

如果用 LangGraph v1.0 实现,可以把多个推理分支做成并行节点,最后用一个汇总节点进行投票或打分:

text
输入问题
  ├── 分支A:生成方案A
  ├── 分支B:生成方案B
  └── 分支C:生成方案C

      汇总节点:比较、投票、输出最终答案

这种方式比在 Prompt 里简单写“多想几遍”更可控,也更方便记录每个分支的结果。

9、如何提高Prompt稳定性?

Prompt 稳定性指的是同样或类似的问题,模型输出不要忽好忽坏、格式不要乱、行为不要漂移。

常见做法有几个。

第一,指令要明确。

不要写“尽量详细”“适当简洁”这种模糊要求。可以写成“输出 3 点,每点不超过 50 字”。

第二,减少冲突指令。

例如前面说“只输出 JSON”,后面又说“请解释原因”,模型就容易输出混合格式。

第三,固定输出模板。

模板越清楚,输出越稳定。

text
请按以下格式输出:
结论:...
原因:...
建议:...

第四,使用 Few-shot 示例。

对于分类、抽取、固定话术等任务,示例可以明显提升稳定性。

第五,降低随机性。

如果模型参数可控,可以降低 temperature,让输出更确定。

第六,把复杂任务拆开。

一个 Prompt 同时要求模型完成理解、检索、计算、总结、格式化,容易不稳定。可以拆成多个步骤,或者在 LangGraph 中拆成多个节点。

第七,程序侧校验。

格式、字段、枚举值、权限这些不能只靠 Prompt,必须用代码校验。

第八,做版本管理。

Prompt 也应该像代码一样管理版本。上线后如果改了 Prompt,要能知道改了什么、影响了哪些效果。

在 LangChain / LangGraph 项目里,可以把提示词模板集中管理,并结合 LangSmith 观察不同版本的调用效果。

10、Prompt过长会有什么问题?

Prompt 过长会带来几个问题。

第一,成本变高。

大模型通常按 Token 计费,Prompt 越长,每次请求成本越高。

第二,速度变慢。

模型需要处理更多上下文,首字响应和整体响应都会变慢。

第三,重点变弱。

Prompt 太长时,真正重要的规则可能被大量背景信息淹没,模型反而不一定遵守。

第四,容易引入噪声。

把很多不相关的历史、文档、规则都放进去,会干扰模型判断。

第五,维护困难。

长 Prompt 往往会不断追加规则,最后谁也说不清哪条规则在起作用,修改一处还可能影响其他场景。

第六,可能超过上下文窗口。

一旦超过模型上下文限制,请求会失败,或者必须截断内容。如果截断位置不合理,关键内容可能丢失。

所以 Prompt 不是越长越好。更好的方式是:

text
固定规则保持简洁
动态内容按需召回
历史信息做摘要
结构化数据用字段传递
复杂流程交给代码或 LangGraph 编排

11、如何优化Prompt Token消耗?

优化 Token 消耗,本质是减少无效上下文,把 Token 用在真正有价值的信息上。

常见方法有几个。

第一,精简固定 Prompt。

删除重复、空泛、无效的描述。比如“你是一个非常聪明、非常专业、非常友好的助手”这种话,对很多任务帮助不大。

第二,使用模板变量。

固定规则写一次,动态内容用变量填充,不要在代码里到处拼接重复文本。

第三,只召回相关内容。

做 RAG 或长期记忆时,不要把所有文档、所有历史记录都放进 Prompt。先检索,再筛选,只放 TopK 相关内容。

第四,使用摘要。

长对话、长文档可以先压缩成摘要,再放入上下文。

第五,结构化表达。

有些信息用 JSON、列表、表格比自然语言更省 Token,也更清晰。

第六,减少 Few-shot 数量。

示例要选最典型的,不要堆太多。很多时候 2 到 5 个高质量示例就够了。

第七,把确定性逻辑交给代码。

比如排序、过滤、格式校验、权限判断,不需要让模型靠 Prompt 完成。代码更便宜、更稳定。

在 LangGraph v1.0 中,可以把任务拆成多个节点,每个节点只拿自己需要的上下文。这样比一个大 Prompt 处理所有事情更省,也更容易排查问题。

12、如何设计Tool Use Prompt?

Tool Use Prompt 的作用,是告诉模型有哪些工具、什么时候用、怎么用、什么时候不要用。

一个好的 Tool Use Prompt 要解决三个问题。

第一,工具是干什么的。

工具名称和描述要清楚,最好一个工具只做一件事。

text
search_docs:搜索企业知识库,用于回答内部制度、产品文档、技术文档相关问题。
get_order:查询订单状态,仅当用户提供订单号时使用。

第二,什么时候调用工具。

text
当问题需要实时信息、外部数据、内部文档或用户业务数据时,必须调用工具。
如果只是解释通用概念,不需要调用工具。

第三,什么时候不要调用工具。

text
如果用户没有提供订单号,不要调用 get_order,而是先询问订单号。
如果用户只是问“什么是订单状态”,不要调用 get_order。

工具 Prompt 还要说明失败处理:

text
如果工具返回为空,回答“没有查到相关信息”,不要编造。
如果工具调用失败,说明当前服务不可用,并建议稍后重试。

在 LangChain v1.0 中,工具一般通过 @tool 或工具对象注册给 Agent,工具的 namedescriptionargs_schema 都会影响模型选择工具:

python
from langchain.tools import tool
from pydantic import BaseModel, Field

class SearchDocsInput(BaseModel):
    query: str = Field(description="要搜索的关键词或问题")

@tool(args_schema=SearchDocsInput)
def search_docs(query: str) -> str:
    """搜索企业知识库。仅用于回答内部文档相关问题。"""
    return "检索结果"

在 LangGraph v1.0 中,工具调用通常会放在专门的 ToolNode 中,Agent 节点负责决定是否调用工具,ToolNode 负责执行工具,然后再回到 Agent 节点生成下一步结果。

流程类似:

text
用户输入

Agent 节点判断是否需要工具
  ↓ 是
ToolNode 执行工具

Agent 节点基于工具结果继续回答

这样做的好处是工具执行逻辑和模型决策逻辑分开,权限校验、日志、重试、人工确认也更容易接进去。

设计 Tool Use Prompt 时,最重要的一点是边界清楚。很多工具误调用,不是模型不行,而是工具描述太模糊,或者多个工具职责重叠。